package IC.Parser;
import java.lang.Integer;



%%

%class Lexer
%public
%function next_token
%type Token
%line
%scanerror LexicalError
%cup

/*check if the file ended in a comment*/
%eofval{
	if (yystate() == COMMENT2) throw new LexicalError(yyline,"the file ended in a comment",null);
	else 
		return new Token(sym.EOF,yyline);
%eofval} 

%state COMMENT1
%state COMMENT2 

/* defining macros */
DIGIT = [0-9]
UPPER_CASE = [A-Z]
LOWER_CASE = [a-z]
LETTER = {LOWER_CASE}|{UPPER_CASE}
ALPHA_NUMERIC = {DIGIT}|{LETTER}|[_]
LINE_TERMINATOR = \r|\n|\r\n
WHITE_SPACE = {LINE_TERMINATOR}|[ \t\f]
ILLEGAL_NUMBER = [0]+{DIGIT}+
NUMBER = {DIGIT}+
 


%%
/*Dealing with spaces and comments*/
<YYINITIAL> "//" {yybegin(COMMENT1);}
<YYINITIAL> "/*" {yybegin(COMMENT2);}
<YYINITIAL> {WHITE_SPACE} {}


<YYINITIAL> "=" {return new Token(sym.ASSIGN,yyline);}
<YYINITIAL> "boolean" {return new Token(sym.BOOLEAN,yyline);}
<YYINITIAL> "break" {return new Token(sym.BREAK,yyline);}
<YYINITIAL> "class" {return new Token(sym.CLASS,yyline);}
<YYINITIAL> "," {return new Token(sym.COMMA,yyline);}
<YYINITIAL> "continue" {return new Token(sym.CONTINUE,yyline);}
<YYINITIAL> "/" {return new Token(sym.DIVIDE,yyline);}
<YYINITIAL> "." {return new Token(sym.DOT,yyline);}
<YYINITIAL> "==" {return new Token(sym.EQUAL,yyline);}
<YYINITIAL> "extends" {return new Token(sym.EXTENDS,yyline);}
<YYINITIAL> "else" {return new Token(sym.ELSE,yyline);}
<YYINITIAL> "false" {return new Token(sym.FALSE,yyline);}
<YYINITIAL> ">" {return new Token(sym.GT,yyline);}
<YYINITIAL> ">=" {return new Token(sym.GTE,yyline);}
<YYINITIAL> "identifier" {return new Token(sym.ID,yyline);}
<YYINITIAL> ">=" {return new Token(sym.GTE,yyline);}
<YYINITIAL> "if" {return new Token(sym.IF,yyline);}
<YYINITIAL> "int" {return new Token(sym.INT,yyline);}
<YYINITIAL> {ILLEGAL_NUMBER} {  throw new LexicalError(yyline,"invalid number",yytext()); }	
<YYINITIAL> {NUMBER} {	try { return new Token(sym.INTEGER,yyline,Integer.parseInt(yytext()));}
						catch (NumberFormatException e) { throw new LexicalError(yyline,"invalid number",yytext()); }}	
<YYINITIAL> "&&" {return new Token(sym.LAND,yyline);}

/* brackets handlers */ 
<YYINITIAL> "[" {return new Token(sym.LB,yyline);}
<YYINITIAL> "]" {return new Token(sym.RB,yyline);}
<YYINITIAL> "(" {return new Token(sym.LP,yyline);}
<YYINITIAL> ")" {return new Token(sym.RP,yyline);}
<YYINITIAL> "{" {return new Token(sym.LCBR,yyline);}
<YYINITIAL> "}" {return new Token(sym.RCBR,yyline);}

<YYINITIAL> "length" {return new Token(sym.LENGTH,yyline);}
<YYINITIAL> "new" {return new Token(sym.NEW,yyline);}
<YYINITIAL> "!" {return new Token(sym.LNEG,yyline);}
<YYINITIAL> "||" {return new Token(sym.LOR,yyline);}
<YYINITIAL> "<" {return new Token(sym.LT,yyline);}
<YYINITIAL> "<=" {return new Token(sym.LTE,yyline);}
<YYINITIAL> "-" {return new Token(sym.MINUS,yyline);}
<YYINITIAL> "%" {return new Token(sym.MOD,yyline);}
<YYINITIAL> "*" {return new Token(sym.MULTIPLY,yyline);}
<YYINITIAL> "!=" {return new Token(sym.NEQUAL,yyline);}
<YYINITIAL> "null" {return new Token(sym.NULL,yyline);}
<YYINITIAL> "+" {return new Token(sym.PLUS,yyline);}
<YYINITIAL> "return" {return new Token(sym.RETURN,yyline);}
<YYINITIAL> ";" {return new Token(sym.SEMI,yyline);}
<YYINITIAL> "static" {return new Token(sym.STATIC,yyline);}
<YYINITIAL> "string" {return new Token(sym.STRING,yyline);}
<YYINITIAL> [\"]([ !#-\[\]-~]|"\\\\"|"\\\""|"\\t"|"\\n")*[\"] {return new Token(sym.QUOTE,yyline,yytext());}      
<YYINITIAL> "this" {return new Token(sym.THIS,yyline);}
<YYINITIAL> "true" {return new Token(sym.TRUE,yyline);}
<YYINITIAL> "void" {return new Token(sym.VOID,yyline);}
<YYINITIAL> "while" {return new Token(sym.WHILE,yyline);}
<YYINITIAL> {UPPER_CASE}({ALPHA_NUMERIC})* {return new Token(sym.CLASS_ID,yyline,yytext());}
<YYINITIAL> {LOWER_CASE}({ALPHA_NUMERIC})* {return new Token(sym.ID,yyline,yytext());}
 <YYINITIAL> "\"" { throw new LexicalError(yyline,"illegal string after '\"' character",null); }  

/*If there is no match throw an exception*/
<YYINITIAL> . { throw new LexicalError(yyline,"illegal character",yytext());}


/* single line comments handlers */
<COMMENT1> [\n] {yybegin(YYINITIAL);}
<COMMENT1> [^\n] {} /*do nothing if the character is not end of line*/

/* multi-line comments handlers */
<COMMENT2> "*/" {yybegin(YYINITIAL);} /*end of comment --> go to yyinital state*/
<COMMENT2> [^\*] {}
<COMMENT2> "*" {}
 
